﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SIA.HwAccess;
using SIA.Configurators;

namespace SIA.Utility.HwCounter
{


    /// <summary>Classe astratta per implementare i contatori, per modificare il valore di contaggio usare la proprietà .Value </summary>
    abstract public class HwCounter : IHwCounter 
    {
        protected String _name;
        protected String _group;
        protected String _comment;
        private long _value = 0;
        protected long _upThreshold = long.MaxValue;
        protected long _downThreshold = long.MinValue;
        protected Nullable<DateTime> _firstIncDateTime;
        protected Nullable<DateTime> _lastIncDateTime;
        protected Nullable<DateTime> _firstDecDateTime;
        protected Nullable<DateTime> _lastDecDateTime;

        protected IHwSignal _upHwSignal;
        protected IHwSignal _downHwSignal;
        protected Boolean _enable = true;
        protected eCounterType _counterType = eCounterType.UP;
        protected IDictionaryProperty _dProperty = new SimpleDictionaryProperty("VOID", "VOID");

        public string Name { get { return _name; } }
        public String Group { get { return _group; } set { _group = value; } }
        public String Comment { get { return _comment; } set { _comment = value; } }
        public IDictionaryProperty DictionaryProperty { get { return _dProperty; } }

        /// <summary>Data Inizio Conteggio</summary>
        public Nullable<DateTime> FirstIncDateTime { get { return _firstIncDateTime; } }
        /// <summary>Data Ultimo Conteggio</summary>
        public Nullable<DateTime> LastIncDateTime { get { return _lastIncDateTime; } }
        /// <summary>Data Inizio Conteggio</summary>
        public Nullable<DateTime> FirstDecDateTime { get { return _firstDecDateTime; } }
        /// <summary>Data Ultimo Conteggio</summary>
        public Nullable<DateTime> LastDecDateTime { get { return _lastDecDateTime; } }
        /// <summary>Segnale di riferimento</summary>
        public IHwSignal UpHwSignal { get { return _upHwSignal; } }
        /// <summary>Segnale di riferimento</summary>
        public IHwSignal DownHwSignal { get { return _downHwSignal; } }
        /// <summary>Abilitazinoe al conteggio</summary>
        public Boolean Enable { get { return _enable; } set { _enable = value; } }
        /// <summary>Valore di soglia per l'evento</summary>
        public long UpThreshold { get { return _upThreshold; } set { _upThreshold = value; } }
        public long DownThreshold { get { return _downThreshold; } set { _downThreshold = value; } }   
        /// <summary>Tipo di Contatore</summary>
        public eCounterType CounterType { get { return _counterType; } set { _counterType = value; } }

        /// <summary>Evento raggiunto lo zero</summary>
        public event dHwCounterEvent ReachedZero;
        /// <summary>Evento data change</summary>
        public event dHwCounterEvent DataChange;
        /// <summary>Evento raggiunta la soglia</summary>
        public event dHwCounterEvent ReachedUpThreshold;
        public event dHwCounterEvent ReachedDownThreshold;

        /// <summary>Valore di Conteggio</summary>
        public long Value { get {
            if (_lastDecDateTime != null && (_lastDecDateTime < DateTime.Now.AddDays(-1)) && _lastIncDateTime != null && (_lastIncDateTime < DateTime.Now.AddDays(-1)))
                _value = 0;
            return _value; 
        } set {
            if (_enable == false) return;
            long lastValue = _value;
            _value = value;

            if (lastValue != _value)
            {
                if (DataChange != null) DataChange(this);

                this.EvaluateThreshold(lastValue, _value);
                this.evaluateDateTime(lastValue, _value);
            }            
        } }

        private void EvaluateThreshold(long lastValue, long actValue)
        {
            if (((actValue >= 0) && (lastValue < 0)) || ((actValue <= 0) && (lastValue > 0)))
                if (ReachedZero != null) ReachedZero(this);

            if (((actValue >= _upThreshold) && (lastValue < _upThreshold)) || ((actValue <= _upThreshold) && (lastValue > _upThreshold)))
                if (ReachedUpThreshold != null) ReachedUpThreshold(this);
            if (((actValue >= _downThreshold) && (lastValue < _downThreshold)) || ((actValue <= _downThreshold) && (lastValue > _downThreshold)))
                if (ReachedDownThreshold != null) ReachedDownThreshold(this);
        }


        private void evaluateDateTime(long lastValue, long actValue)
        {
            if (lastValue == 0 && actValue != 0)
            {
                _firstIncDateTime = null;
                _firstDecDateTime = null;
            }

            if (actValue > lastValue && _firstIncDateTime == null)
                _firstIncDateTime = DateTime.Now;

            if (actValue < lastValue && _firstDecDateTime == null)
                _firstDecDateTime = DateTime.Now;

            if (actValue > lastValue)
                _lastIncDateTime = DateTime.Now;

            if (actValue < lastValue)
                _lastDecDateTime = DateTime.Now;           
        }

        #region IHwCounter Membri di


        public void decreases()
        {
            this.decreases(1);
        }

        public void decreases(int value)
        {
            this.Value = this.Value - value;
        }

        public void increases()
        {
            this.increases(1);
        }

        public void increases(int value)
        {
            this.Value = this.Value + value;
        }

        #endregion
    }   
}
